/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package towerz.game;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import towerz.system.Utilities;
import towerz.system.xml.XmlNode;
import towerz.system.xml.XmlReaderWriter;

/**
 *
 * @author LegACy
 */
public class Sprite {
	protected class Tint {
		public Tint() {
			m_Tint		= 0;
			m_Wait		= 0;
			m_Timer		= 0;
			m_Active	= true;
		}

		//Public
		public Tint(int tint, long time) {
			//Default
			this();

			//Save data
			m_Wait	= time;
			m_Tint	= tint;
		}

		public int getTint()		{	return m_Tint;		}
		public boolean isActive()	{	return m_Active;	}
		
		public void update(long time) {
			//If there's wait
			if (m_Active && m_Wait > 0) {
				//Increase timer
				m_Timer += time;

				//If done, deactivate
				if (m_Timer >= m_Wait) m_Active = false;
			}
		}

		//members
		protected int		m_Tint;
		protected long		m_Wait;
		protected long		m_Timer;
		protected boolean	m_Active;
	}

	protected Sprite() {
		//Initialize
		m_X			= 0;
		m_Y			= 0;
		m_Frame		= 0;
		m_Delay		= 0;
		m_Timer		= 0;
		m_Width		= 0;
		m_Height	= 0;
		m_Images	= null;
		m_Animating	= true;
		m_Tints		= new Vector();

		//Check hash table
		if (s_Tints == null) Sprite.readTintData();
	}

	public Sprite(String image, int row, int column) throws IOException {
		this(image, 0, 0, row, column, 0);
	}

	public Sprite(String image, int x, int y, int row, int column) throws IOException {
		this(image, x, y, row, column, 0);
	}

	public Sprite(String image, int xPos, int yPos, int row, int column, long delay) throws IOException {
		this(new Image[]{Image.createImage(image)}, xPos, yPos, row, column, delay);
	}

	public Sprite(Image[] images, int xPos, int yPos, int row, int column, long delay) {
		//Default
		this();

		//Set position
		m_X = xPos;
		m_Y = yPos;

		//Create images
		m_Images = new Image[images.length][row * column];

		//Set width and row
		m_Width		= images[0].getWidth() / column;
		m_Height	= images[0].getHeight() / row;

		//Splice image
		for (int i = 0; i < images.length; i++)
			for (int x = 0; x < column; x++)
				for (int y = 0; y < row; y++)
					m_Images[i][(y * column) + x] = Image.createImage(images[i], x * m_Width, y * m_Height, m_Width, m_Height, 0);

		//Set delay
		m_Delay = delay;
		if (m_Delay > 0) m_Animating = true;
	}

	public Sprite(Image[][] images, int xPos, int yPos, long delay) {
		//Default
		this();

		//Set position
		m_X			= xPos;
		m_Y			= yPos;
		m_Images	= images;
		m_Width		= images[0][0].getWidth();
		m_Height	= images[0][0].getWidth();

		//Set delay
		m_Delay = delay;
		if (m_Delay > 0) m_Animating = true;
	}

	public static void readTintData() {
		//Instantiate hashtable
		s_Tints = new Hashtable();

		//Read xml
		XmlNode XML = XmlReaderWriter.getInstance().readFromXmlFile(Utilities.TINTDATA_FILE);

		//For each child
		for (int i = 0; i < XML.getChildren().size(); i++) {
			//Default
			int Index = -1;
			int Color = 0x00000000;

			//Check child name
			if (((XmlNode)XML.getChildren().elementAt(i)).getNodeName().equals("tint")) {
				//Get node
				XmlNode TintNode	= (XmlNode)XML.getChildren().elementAt(i);
				Index				= Integer.parseInt(TintNode.getAttribute("index"));

				//Get color
				for (int j = 0; j < TintNode.getChildren().size(); j++) {
					//If color
					if (((XmlNode)TintNode.getChildren().elementAt(j)).getNodeName().equals("color")) {
						//Get data
						int A = Integer.parseInt(((XmlNode)TintNode.getChildren().elementAt(j)).getAttribute("a"));
						int R = Integer.parseInt(((XmlNode)TintNode.getChildren().elementAt(j)).getAttribute("r"));
						int G = Integer.parseInt(((XmlNode)TintNode.getChildren().elementAt(j)).getAttribute("g"));
						int B = Integer.parseInt(((XmlNode)TintNode.getChildren().elementAt(j)).getAttribute("b"));

						//Set color
						Color = (A << 24) | (R << 16) | (G << 8) | B;
					}
				}

				//Check index
				if (Index >= 0) {
					s_Tints.put(new Integer(Index), new Integer(Color));
				}
			}
		}
	}

	public static int getTint(int index) {
		//Default tint
		int Tint = 0x00000000;

		//Find tint
		if (s_Tints != null) {
			Integer TintInteger = (Integer)s_Tints.get(new Integer(index));
			if (TintInteger != null) Tint = TintInteger.intValue();
		}

		//Return tint
		return Tint;
	}

	public static int[] getTints() {
		//1 is null
		if (s_Tints == null) return new int[]{0x00000000};

		//Prepare variable
		int[] Tints = new int[s_Tints.size() + 1];
		Tints[0]	= 0x00000000;

		//Read
		for (int i = 0; i < s_Tints.size(); i++)
			Tints[i + 1] = Sprite.getTint(i + 1);

		//return tints
		return Tints;
	}

	public int getWidth() {
		return m_Width;
	}

	public int getHeight() {
		return m_Height;
	}

	public void setAnimating(boolean animating) {
		//Set animation
		m_Animating = true;
	}

	public void setFrame(int frame) {
		//Set frame
		m_Frame = frame;

		//Correct frame
		if (m_Frame < 0)					m_Frame = 0;
		if (m_Frame > m_Images[0].length)	m_Frame = m_Images[0].length - 1;
	}

	public void setPosition(int x, int y) {
		m_X = x;
		m_Y = y;
	}

	public void setTilePosition(int x, int y, int offsetX, int offsetY) {
		//Set position
		m_X = (x * Utilities.TILE_WIDTH)  + offsetX;
		m_Y = (y * Utilities.TILE_HEIGHT) + offsetY;
	}

	public void addTint(int color, long delay) {
		//Add new tint
		m_Tints.addElement(new Tint(color, delay));
	}

	public void update(long time) {
		//If animating
		if (m_Animating) {
			//Increase timer
			m_Timer += time;

			//If more than delay
			if (m_Timer >= m_Delay) {
				//Reset
				m_Timer -= m_Delay;

				//Next frame
				m_Frame++;
				if (m_Frame >= m_Images[0].length) m_Frame = 0;
			}
		}
		
		//Update animated
		Vector DeletedTints = new Vector();
		for (int i = 0; i < m_Tints.size(); i++) {
			((Tint)m_Tints.elementAt(i)).update(time);
			if (!((Tint)m_Tints.elementAt(i)).isActive()) DeletedTints.addElement(m_Tints.elementAt(i));
		}

		//Kill dead tints
		for (int i = 0; i < DeletedTints.size(); i++) m_Tints.removeElement(DeletedTints.elementAt(i));
		DeletedTints.removeAllElements();
	}

	public void draw(Graphics g) {
		//Get last tint
		int Current = 0;
		if (!m_Tints.isEmpty()) Current = ((Tint)m_Tints.lastElement()).getTint();

		//Draw
		g.drawImage(m_Images[Current][m_Frame], m_X, m_Y, Graphics.LEFT | Graphics.TOP);
	}
	
	//Tint colors
	protected static Hashtable s_Tints;

	//Data
	protected int		m_X;
	protected int		m_Y;
	protected int		m_Width;
	protected int		m_Height;
	protected Image[][]	m_Images;

	//Animation
	protected int		m_Frame;
	protected long		m_Delay;
	protected long		m_Timer;
	protected Vector	m_Tints;
	protected boolean	m_Animating;
}
